//! \file file.hpp
//! \brief Purewell Library File Header
//! \author Yubin Lim (purewell@gmail.com)
//! \since 2008-01-25

#ifndef __PWHDR_FILE_HPP__
#define __PWHDR_FILE_HPP__

#include <string>

namespace purewell
{

class PWFileUtil;
class PWIOPoll;

//! \brief File handler.
class PWFile
{
public:
	//! \brief Get file descriptor.
	//! \return File descriptor.
	inline int getHandle(void) const
	{
		return m_fd;
	}

	//! \brief Destroy.
	virtual void destroy(void);

	//! \brief Attach file descriptor.
	//! \return On success, true.
	virtual bool attach(int fd);

	//! \brief Detach file descriptor.
	//! \return Detached file descriptor.
	virtual int detach(void);

	//! \brief Read data from file descriptor.
	//! \param[out] buf Buffer.
	//! \param[in] blen Buffer length.
	//! \return On success, read size. In case of error, it returns -1.
	virtual ssize_t read(void* buf, size_t blen);

	//! \brief Read data from file descriptor parallely.
	//! \param[out] buf Buffer.
	//! \param[in] blen Buffer length.
	//! \param[in] offset Offset to read.
	//! \return On success, read size. In case of error, it returns -1.
	virtual ssize_t readParallel(void* buf, size_t blen, off_t offset);

	//! \brief Write data to file descriptor.
	//! \param[in] buf Buffer.
	//! \param[in] blen Buffer length.
	//! \return On success, written size. In case of error, it returns -1. 
	virtual ssize_t write(const void* buf, size_t blen);

	//! \brief Write data to file descriptor parallely.
	//! \param[in] buf Buffer.
	//! \param[in] blen Buffer length.
	//! \param[in] offset Offset to write.
	//! \return On success, read size. In case of error, it returns -1.
	virtual ssize_t writeParallel(const void* buf, size_t blen,
		off_t offset);

public:
	// File controls

	//! \brief Set blocking mode.
	//! \param[in] block Blocking mode.
	//! \return On success, true.
	bool setModeBlock(bool block);

	//! \brief Get blocking mode.
	//! \param[out] block Blocking mode.
	//! \return On success, true.
	bool getModeBlock(bool& block) const;

	//! \brief Set asynchronous mode.
	//! \param[in] async Asynchronous mode.
	//! \return On success, true.
	bool setModeAsync(bool async);

	//! \brief Get asynchronous mode.
	//! \param[out] async Asynchronous mode.
	//! \return On success, true.
	bool getModeAsync(bool& block) const;

	//! \brief Set mode close on exec.
	//! \param[in] coe Close on exec mode.
	//! \return On success, true.
	bool setModeCloseOnExec(bool coe);

	//! \brief Get mode close on exec.
	//! \param[out] coe Close on exec mode.
	//! \return On success, true.
	bool getModeCloseOnExec(bool& coe) const;

	//! \brief Set mode.
	//! \param[in] mode Mode flags.
	//! \return On success, true.
	bool setMode(int mode);

	//! \brief Get mode.
	//! \param[out] mode Mode flags.
	//! \return On success, true.
	bool getMode(int& mode) const;

	//! \brief Duplicate file descriptor.
	//! \param[in] srcfd Source file descriptor.
	//! \return On success, true.
	//! \warning Without destroy method, initialized file descriptor will be leaked.
	bool duplicate(int srcfd);

	//! \brief Duplicate file descriptor.
	//! \param[in] srcfd Source file descriptor.
	//! \param[in] newfd New file descriptor to allocate.
	//! \return On success, true.
	//! \warning Without destroy method, initialized file descriptor will be leaked.
	bool duplicate(int srcfd, int newfd);

public:
	//! \brief Callback-interface for PWIOPoll.
	//! \param[in,out] io Caller.
	//! \param[in] fd File descriptor.
	//! \param[in] event Events.
	virtual void onEvent(PWIOPoll* io, int fd, int event);

public:
	explicit PWFile();
	virtual ~PWFile();

private:
	explicit PWFile(const PWFile&) {}
	PWFile& operator = (const PWFile&) {return *this;}

protected:
	int			m_fd;	//!< File descriptor.

	friend class PWFileUtil;
};

//! \brief Named file interface.
class PWNamedFile : public PWFile
{
public:
	//! \brief Initialize file object.
	//! \param[in] name File name.
	//! \param[in] flag Open flag.
	//! \param[in] perm Permittion. 
	//! \return On success, true.
	virtual bool initialize(const char* name, int flag, int perm);

	//! \brief Get name.
	//! \return Name string(C-style).
	const char* getName(void) const;

	virtual int detach(void);

	//! \brief Unlink file.
	//! \return On success, true.
	virtual bool unlink(void);

public:
	explicit PWNamedFile();
	virtual ~PWNamedFile();

protected:
	std::string m_name;		//!< File name.

	friend class PWFileUtil;
};

};

#endif//!__PWHDR_FILE_HPP__

